#pragma once
#include <vector>
#include <pthread.h>
#include <semaphore.h>

namespace RingQueue
{
    template <typename T>
    class ringQueue
    {
    public:
        ringQueue(int cap)
            : que(cap), _cap(cap), _producter_Index(0), _consumer_Index(0)
        {
            sem_init(&empty_sem, 0, cap);
            sem_init(&space_sem, 0, 0);
            pthread_mutex_init(&producter_mutex,nullptr);
            pthread_mutex_init(&consumuer_mutex,nullptr);
        }

        ~ringQueue()
        {
            sem_destroy(&empty_sem);
            sem_destroy(&space_sem);
        }

        void getData(T *data) // 从循环队列中获取数据
        {
            //pthread_mutex_lock(&consumuer_mutex);
            p(space_sem);
            pthread_mutex_lock(&consumuer_mutex);
            *data = que[_consumer_Index++];
            _consumer_Index %= _cap;
            pthread_mutex_unlock(&consumuer_mutex);
            v(empty_sem);
            //pthread_mutex_unlock(&consumuer_mutex);
        }

        void pushData(const T &data) // 往循环队列中放入数据
        {
            p(empty_sem);
            pthread_mutex_lock(&producter_mutex);
            que[_producter_Index++] = data;
            _producter_Index %= _cap;
            pthread_mutex_unlock(&producter_mutex);
            v(space_sem);
        }

    private:
        std::vector<T> que;
        int _cap;
        int _producter_Index;
        int _consumer_Index;
        sem_t empty_sem;
        sem_t space_sem;
        pthread_mutex_t producter_mutex;
        pthread_mutex_t consumuer_mutex;

        // p操作
        void p(sem_t &sem)
        {
            sem_wait(&sem);
        }
        // v操作
        void v(sem_t &sem)
        {
            sem_post(&sem);
        }
    };
}
